_Pragma("once");

#include <memory>
#include <string>
#include <sstream>
#include <cstdio>
#include <string_view>

#include "Log.h"
#include "Screen.h"
#include "KeypadListener.h"
#include "CharPoint.h"

enum EditorType : int {
    /**
     * 可编辑类型 数字
     */
    NUMBER = 1,

    /**
     * 可编辑类型 字符
     */
    STRING_LIST = 2,

    BUTTON = 3,
    STRING = 4,
    /**
     * 编辑时的刷新间隔
     */
};

class BasicEditor : public KeypadListener {
public:

    BasicEditor(EditorType editorType) : BasicEditor(0, 0, 8, editorType) {
    }

    BasicEditor(int lineNum, int startPos, int endPos, EditorType editorType);
    virtual ~BasicEditor() {
    }

    /**
     * Editor开始闪烁
     */
    void setFocus(bool focus) {
        this->focus = focus;
    }

    virtual void paint(bool forcePaintValue = false) {
        if (focus || forcePaintValue) {
            if (forcePaintValue) {
                showBlank = false;
            } else {
                showBlank = !showBlank;
            }
            const std::string& text = showBlank ? blankText : getText();
            screen.show(point.x, point.y, text);
        }

    }


    int onKeySet(const KeyCode& keyCode) override {
        return 0;
    }

    int onKeyEnt(const KeyCode& keyCode) override {
        return 0;
    }

    int onOtherKey(const KeyCode& keyCode) override {
        return 0;
    }


    virtual const std::string& getText() = 0;

    operator std::string() {
        std::ostringstream oss;
        oss << "lineNum=" << this->point.y  << " startPos=" << this->point.x << " endPos=" << this->endPos;

        return oss.str();
    }


    int operator < (const BasicEditor& o);

    std::string format = "%4d";

protected:
    CharPoint point;
    /**
     * 结束x坐标
     */
    int endPos;
    /**
     * 可编辑类型  数字 字符
     */
    EditorType editorType;
    /**
     * 闪烁标志,显示空白或实际值
     */
    volatile bool showBlank = false;

    std::string blankText;

    bool focus;

    std::string textBuffer;
    size_t maxCharactor;

    static Screen& screen;
};



/**
 * 编辑页面工具类
 *
 * @author lizb
 */
template<class T, class RANGE_TYPE = T>
class Editor : public BasicEditor {
public:

    Editor(EditorType editorType) : Editor(0, 0, 8, editorType, 1) {
    }

    Editor(int lineNum, int startPos, int endPos, EditorType editorType, RANGE_TYPE step = 1);


    virtual bool setValue(const T& value) {
        this->value = value;

        return true;
    }


    virtual bool setValueByRange(const RANGE_TYPE& value) {

        this->value = value;

        return true;
    }

    virtual const T& getValue() {
        return value;
    }

    const std::string& getText() override {
        std::snprintf(&textBuffer.at(0), maxCharactor + 1, format.data(), value);
        textBuffer.resize(maxCharactor);
        return textBuffer;
    }

    /**
     * Down键  数值减小
     */
    int onKeyDown(const KeyCode& keyCode) override  {
        if (setValueByRange(value - step)) {
            paint();
        }

        return 1;
    }

    /**
     * UP键 数值增加
     */
    int onKeyUp(const KeyCode& keyCode) override {
        if (setValueByRange(value + step)) {
            paint();
        }

        return 1;
    }


protected:
    T value;

    const RANGE_TYPE step;
};



/**
 * 待定lineNum和pos从1开始
 */
template<class T, class RANGE_TYPE>
Editor<T, RANGE_TYPE>::Editor(int lineNum, int startPos, int endPos, EditorType editorType, RANGE_TYPE step) : BasicEditor(lineNum, startPos, endPos, editorType), step(step) {

}


using BasicEditorSharedPtr = std::shared_ptr<BasicEditor>;


